
#include "mpi_lib.h"
#include "mpi.h"
#include "mpi_cmd.h"
#include "mpi_vo.h"
#include "mpi_sys.h"
#include "mpi_cap.h"
#include "mdi_common.h"


int sgks_mpi_cap_MmapPhyAddr(sgks_mpi_manager_s *mpi)
{
    u8 *msg_buf = NULL;
    SGKS_MDI_DRV_BUFF(msg_buf);
    sgks_mdi_mmap_s *mmap_info = msg_buf;

    SGKS_MDI_DRV_CLEAN_DATABUFF();
    mmap_info->mmap_phy_start_addr = (u8 *)mpi->mpi_init_param.dsp_init_param.DSP_buf_ptr_phy;
    mmap_info->mmap_phy_size       = (int)mpi->mpi_init_param.dsp_init_param.DSP_buf_size;
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_MMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);
    mpi->cap_base_ptr_vir  = (u8 *)mmap_info->mmap_user_start_addr;
    //Printf("cap map: phy addr 0x%x ----> vir 0x%x  size 0x%x\n",mmap_info->mmap_phy_start_addr,mmap_info->mmap_user_start_addr, mmap_info->mmap_user_size);

    return SGKS_SUCCESS;
}

int sgks_mpi_cap_YuvRescale(sgks_mpi_cap_yuv_rescale_s *yuv_rescale)
{

    unsigned int i;

    sgks_mpi_manager_s *mpi = mpi_get_managerHanle();

    sgks_dsp_cmd_pip_config_default_s *pip_config=&mpi->mpi_vo_dev[0].pip_config_default;

    pip_config->rescale_num = 1;
    pip_config->yuv_type = yuv_rescale->yuv_type;

    for(i = 0; i < pip_config->rescale_num; i++)
    {
        pip_config->rescale_width[i] = yuv_rescale->width;
        pip_config->rescale_height[i] = yuv_rescale->height;
    }
    sgks_mpi_vo_pip_config(&mpi->mpi_vo_dev[0]);

    return SGKS_SUCCESS;
}

int sgks_mpi_cap_Init(sgks_mpi_cap_init_param_s *cap_init_param)
{
    int ret = -1;

    sgks_mpi_manager_s *mpi = mpi_get_managerHanle();

	memcpy(&mpi->cap_init_param, cap_init_param,sizeof(sgks_mpi_cap_init_param_s));

    ret = sgks_mpi_cap_MmapPhyAddr(mpi);
    if (ret != SGKS_SUCCESS)
    {
        return ret;
    }

	if (mpi->cap_init_param.cap_type==SGKS_CAP_YUV_SOURCE_TYPE_VIN_RESCALE) 
	{
		sgks_mpi_cap_YuvRescale(&mpi->cap_init_param.yuv_rescale);
	}	

    return SGKS_SUCCESS;
}

int sgks_mpi_cap_GetData(sgks_mpi_cap_yuv_info_s *yuv_info)
{
	int ret = 0;
    u8 *msg_buf = NULL;
    SGKS_MDI_DRV_BUFF(msg_buf);

    switch (yuv_info->source_type)
    {
    case SGKS_CAP_YUV_SOURCE_TYPE_CVBS_DMA:
    {
        sgks_mpi_manager_s *mpi = mpi_get_managerHanle();
        sgks_mdi_reg_rw_s *reg = msg_buf;

        unsigned int y_base_addr, uv_base_addr, frame_num;
        volatile unsigned int *read_ptr_reg 		= 0xf0020510;
        unsigned int *frame_num_reg 				= 0xf0020400;
        unsigned int *dvp_y_addr					= 0xf0020408;
        static unsigned int fifo_read_old			= 0xffffffff;
        unsigned short fifo_ptr;
        unsigned char fifo_read_ptr, fifo_write_ptr;
		int i = 0 ;

        unsigned int read_reg;
        unsigned int frame_reg;
        unsigned int dvp_y0;
		unsigned int dvp_y1;
		unsigned int dvp_y2;
		unsigned int dvp_y3;

        /* wait nextest frame */
        while(1)
        {
            SGKS_MDI_DRV_CLEAN_DATABUFF();
            reg->reg_num =1;
            reg->reg_info[0].addr	   = read_ptr_reg;
            reg->reg_info[0].addr_type = SGKS_MDI_REG_ADDR_TYPE_VIR;

            SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_REG_READ, 0, sizeof(sgks_mdi_reg_rw_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

            read_reg = reg->reg_info[0].val;

            fifo_ptr = read_reg;
            fifo_read_ptr = fifo_ptr & 0x00FF;
            if(fifo_read_ptr == fifo_read_old)
            {
                if(yuv_info->stride & 0x80000000)
                {
                    //no block
                    return -EAGAIN;
                }
                else
                {
                    usleep(1000);
                    continue;
                }
            }

            fifo_read_old = fifo_read_ptr;
            break;
        }

        SGKS_MDI_DRV_CLEAN_DATABUFF();
        reg->reg_num =1;
        reg->reg_info[0].addr      = frame_num_reg;
        reg->reg_info[0].addr_type = SGKS_MDI_REG_ADDR_TYPE_VIR;

        SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_REG_READ, 0, sizeof(sgks_mdi_reg_rw_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

        frame_reg = reg->reg_info[0].val;
        frame_num 		       = (((fifo_ptr - 1) & 0x00FF) & 0xff) % ((frame_reg >> 8) & 0xff);

        SGKS_MDI_DRV_CLEAN_DATABUFF();
        reg->reg_num = 4;
        reg->reg_info[0].addr      = dvp_y_addr + 1 + frame_num * 4;
        reg->reg_info[0].addr_type = SGKS_MDI_REG_ADDR_TYPE_VIR;
		
		reg->reg_info[1].addr      = dvp_y_addr + frame_num * 4;
        reg->reg_info[1].addr_type = SGKS_MDI_REG_ADDR_TYPE_VIR;
		
		reg->reg_info[2].addr      = dvp_y_addr + 3 + frame_num * 4;
        reg->reg_info[2].addr_type = SGKS_MDI_REG_ADDR_TYPE_VIR;
		
		reg->reg_info[3].addr      = dvp_y_addr + 2 + frame_num * 4;
        reg->reg_info[3].addr_type = SGKS_MDI_REG_ADDR_TYPE_VIR;

        SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_REG_READ, 0, sizeof(sgks_mdi_reg_rw_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

        dvp_y0 = reg->reg_info[0].val;
		dvp_y1 = reg->reg_info[1].val;
		dvp_y2 = reg->reg_info[2].val;
		dvp_y3 = reg->reg_info[3].val;
		
        y_base_addr            = ((dvp_y0 & 0xffff) << 16) | (dvp_y1 & 0xffff);
        uv_base_addr 	       = ((dvp_y2 & 0xffff) << 16) | (dvp_y3 & 0xffff);
        yuv_info->yAddr        = mpi->cap_base_ptr_vir + (y_base_addr - (unsigned int)mpi->mpi_init_param.dsp_init_param.DSP_buf_ptr_phy);
        yuv_info->uvAddr       = mpi->cap_base_ptr_vir + (uv_base_addr - (unsigned int)mpi->mpi_init_param.dsp_init_param.DSP_buf_ptr_phy);
		for (i = 0; i < mpi->vi_device.vi_device_num; i++)
		{
			if (mpi->vi_device.vi_deviceinfo[i].vi_type == SGKS_VI_TYPE_DMA && mpi->vi_device.vi_deviceinfo[i].enable == 1)
				break;
		}
		yuv_info->width        = mpi->vi_device.vi_deviceinfo[i].cap_width;
    	yuv_info->height       = mpi->vi_device.vi_deviceinfo[i].cap_height;
        yuv_info->stride       = yuv_info->width;
        yuv_info->frameFormat  = 0;
        yuv_info->addr_type    = 0;

		break;
    }
    case SGKS_CAP_YUV_SOURCE_TYPE_VIN:
    {
        sgks_mpi_manager_s *mpi = mpi_get_managerHanle();
        sgks_mdi_yuv_info_s *yuvdata 		= msg_buf;

        SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_GET_YUV_INFO, 0, sizeof(sgks_mdi_yuv_info_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

        yuv_info->yAddr        = mpi->cap_base_ptr_vir + yuvdata->encode_y_pic_addr;
        yuv_info->uvAddr       = mpi->cap_base_ptr_vir + yuvdata->encode_uv_pic_addr;
        yuv_info->width        = yuvdata->encode_yuv_pitch;
        yuv_info->height       = yuvdata->encode_yuv_height;
        yuv_info->stride       = yuvdata->encode_yuv_pitch;
        yuv_info->frameFormat  = 0;
        yuv_info->addr_type    = 0;
        break;
    }
    case SGKS_CAP_YUV_SOURCE_TYPE_VIN_RESCALE:
    {
        sgks_mpi_manager_s *mpi = mpi_get_managerHanle();
        sgks_mdi_yuv_info_s *yuvdata 		= msg_buf;

        SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_GET_YUV_INFO, 0, sizeof(sgks_mdi_yuv_info_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

        yuv_info->yAddr = mpi->cap_base_ptr_vir + yuvdata->rescale_y_pic_addr;
        yuv_info->uvAddr = mpi->cap_base_ptr_vir + yuvdata->rescale_uv_pic_addr;
        yuv_info->width = yuvdata->rescale_yuv_pitch;
        yuv_info->height = yuvdata->rescale_yuv_height;
        yuv_info->stride = yuvdata->rescale_yuv_pitch;
        yuv_info->frameFormat = 1;
        yuv_info->addr_type = 0;
        break;
    }
    case SGKS_CAP_YUV_SOURCE_TYPE_VDEC_RAW:
    {
        sgks_mpi_manager_s *mpi = mpi_get_managerHanle();
        sgks_mdi_yuv_info_s *yuvdata 		= msg_buf;

        SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_GET_YUV_INFO, 0, sizeof(sgks_mdi_yuv_info_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

        yuv_info->yAddr = mpi->cap_base_ptr_vir + yuvdata->jpeg_y_addr;
        yuv_info->uvAddr = mpi->cap_base_ptr_vir + yuvdata->jpeg_uv_addr;
        yuv_info->width = yuvdata->jpeg_pitch;
        yuv_info->height = yuvdata->jpeg_height;
        yuv_info->stride = yuvdata->jpeg_pitch;
        yuv_info->frameFormat = 0;
        yuv_info->addr_type = 0;
        break;
    }
	case SGKS_CAP_YUV_SOURCE_TYPE_VDEC_SCREEN:
    {
        sgks_mpi_manager_s *mpi = mpi_get_managerHanle();
        sgks_mdi_yuv_info_s *yuvdata 		= msg_buf;

        SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_GET_YUV_INFO, 0, sizeof(sgks_mdi_yuv_info_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

        yuv_info->yAddr = mpi->cap_base_ptr_vir + yuvdata->yuv422_y_addr;
        yuv_info->uvAddr = mpi->cap_base_ptr_vir + yuvdata->yuv422_uv_addr;
        yuv_info->width = yuvdata->yuv422_pitch;
        yuv_info->height = yuvdata->yuv422_height;
        yuv_info->stride = yuvdata->yuv422_pitch;
        yuv_info->frameFormat = 1;
        yuv_info->addr_type = 0;		
        break;
    }
    case SGKS_CAP_YUV_SOURCE_TYPE_VDEC_RESCALE: 
    {
        sgks_mpi_manager_s *mpi = mpi_get_managerHanle();
        sgks_mdi_yuv_info_s *yuvdata 		= msg_buf;

        SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_GET_YUV_INFO, 0, sizeof(sgks_mdi_yuv_info_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

        yuv_info->yAddr = mpi->cap_base_ptr_vir + yuvdata->second_rescale_buf_address_y;
        yuv_info->uvAddr = mpi->cap_base_ptr_vir + yuvdata->second_rescale_buf_address_uv;
        yuv_info->width = yuvdata->second_rescale_buf_pitch;
        yuv_info->height = yuvdata->second_rescale_buf_height;
        yuv_info->stride = yuvdata->second_rescale_buf_pitch;
        yuv_info->frameFormat = 1;
        yuv_info->addr_type = 0;
        break;
    }
    default:
    {
        printf("source  type: %d error\n", yuv_info->source_type);
        return -1;
    }

    }

    return SGKS_SUCCESS;

}


